home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / gawk / cawf2st.zoo / fontfilt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-12  |  24.8 KB  |  811 lines

  1. /*
  2.  * fontfilt.c - cawf post-processing font filter
  3.  *
  4.  * V. Abell
  5.  * Purdue University Computing Center
  6.  *
  7.  * Fontfilt filters output from cawf, the C version of Henry Spencer's
  8.  * Amazingly Workable (text) Formatter, awf, to produce printer-specific
  9.  * codes for bold and italic characters.  (Cawf provides modest support
  10.  * for documents formatted with nroff's man(7) and ms(7) macros.)
  11.  *
  12.  * Fontfilt is based on work by and suggestions from Chet Creider
  13.  * <creider@csd.uwo.ca>.
  14.  */
  15.  
  16.  
  17. /*
  18.  *      Copyright (c) 1991 Purdue University Research Foundation,
  19.  *      West Lafayette, Indiana 47907.  All rights reserved.
  20.  *
  21.  *      Written by Victor A. Abell <abe@mace.cc.purdue.edu>, Purdue
  22.  *      University Computing Center.  Not derived from licensed software;
  23.  *      derived from work by Chet Creider <creider@csd.uwo.ca>.
  24.  *
  25.  *      Permission is granted to anyone to use this software for any
  26.  *      purpose on any computer system, and to alter it and redistribute
  27.  *      it freely, subject to the following restrictions:
  28.  *
  29.  *      1. The author is not responsible for any consequences of use of
  30.  *         this software, even if they arise from flaws in it.
  31.  *
  32.  *      2. The origin of this software must not be misrepresented, either
  33.  *         by explicit claim or by omission.  Credits must appear in the
  34.  *         documentation.
  35.  *
  36.  *      3. Altered versions must be plainly marked as such, and must not
  37.  *         be misrepresented as being the original software.  Credits must
  38.  *         appear in the documentation.
  39.  *
  40.  *      4. This notice may not be removed or altered.
  41.  */
  42.  
  43.  
  44. /*
  45.  * Usage:
  46.  *
  47.  *      fontfilt [-c config] [-d device] [-f font] [file(s)]
  48.  *
  49.  *      where:
  50.  *
  51.  *              -c config       specifies an alternate configuration file
  52.  *                              (default directory = CAWFLIB definition or
  53.  *                                                   CAWFLIB env. variable)
  54.  *
  55.  *              -d device       specifies the output device
  56.  *
  57.  *              -f font         specifies the font to be used on the
  58.  *                              output device
  59.  *
  60.  *              file(s)         the path(s) to the file(s) containing cawf,
  61.  *                              -fe format output
  62.  *
  63.  * Cawf's font ESCape mode must be used - e. g.,
  64.  *
  65.  *      % cawf -fe -man cawf.1 | fontfilt -dlj3 -flg12
  66.  */
  67.  
  68.  
  69. /*
  70.  * See fontfilt.cf for a list of supported devices and fonts, or use
  71.  * the -h (help) option.  The default device is the last device named
  72.  * in fontfilt.cf.
  73.  */
  74.  
  75. #include <stdio.h>
  76. #ifdef  STDLIB
  77. #include <stdlib.h>
  78. #endif
  79. #ifdef  UNIX
  80. #ifdef  USG
  81. #include <string.h>
  82. #else
  83. #include <strings.h>
  84. #endif
  85. #else
  86. #include <string.h>
  87. #endif
  88. #include <ctype.h>
  89. #include <sys/types.h>
  90. #include <sys/stat.h>
  91.  
  92. #include "cawflib.h"
  93.  
  94.  
  95. /*
  96.  * Local definitions
  97.  */
  98.  
  99. #define BOLD            'B'
  100. #define CONFIG          "fontfilt.cf"
  101. #define ESC             0x1b
  102. #define ITALIC          'I'
  103. #define MAXLINE         512
  104. #define ROMAN           'R'
  105.  
  106.  
  107. /*
  108.  * Local global variables
  109.  */
  110.  
  111. static char *Besc = NULL;       /* bold font escape string pointer */
  112. static char *Conf = NULL;       /* configuration file path */
  113. static char *Defdev = NULL;     /* default device name (last name of
  114.                                  * fontfilt.cf */
  115. static char Font = ROMAN;       /* current font */
  116. static char *Iesc = NULL;       /* italic font escape string pointer */
  117. static char *Pname;             /* program name */
  118. static char *Resc = NULL;       /* roman font escape string pointer */
  119.  
  120.  
  121. /*
  122.  * Structure for font definitions
  123.  */
  124.  
  125. struct font {
  126.         char *nm;               /* font name */
  127.         char *fi;               /* font initialization character sequence */
  128.         struct font *next;      /* next font fot this device */
  129. };
  130.  
  131.  
  132. /*
  133.  * Device structure
  134.  */
  135.  
  136. struct dev {
  137.         char *nm;               /* device name */
  138.         struct font *f;         /* supported fonts */
  139.         char *b;                /* bold font ESCape sequence */
  140.         char *i;                /* italic font ESCape sequence */
  141.         char *r;                /* Roman font ESCape sequence */
  142.         struct dev *next;       /* next device */
  143. } *Dp = NULL;
  144.  
  145.  
  146. /*
  147.  * Externals
  148.  */
  149.  
  150. extern char *optarg;                    /* getopt(3) argument pointer */
  151. extern int optind;                      /* getopt(3) index */
  152.  
  153.  
  154. /*
  155.  * Function definitions
  156.  */
  157.  
  158. static char *Convstr();
  159. static int Convfont(), Readcf();
  160. static void Bold(), Getec(), Italic(), Roman();
  161.  
  162. #ifndef STDLIB
  163. char *getenv(), *malloc(), *strchr(), *strrchr();
  164. #endif
  165.  
  166.  
  167. /*
  168.  * Main program
  169.  */
  170.  
  171. main(argc, argv)
  172.         int argc;                       /* argument count */
  173.         char *argv[];                   /* argument pointers */
  174. {
  175.         register int c;                 /* character buffer */
  176.         char *cnm = NULL;               /* config file name */
  177.         char *dnm = NULL;               /* device name */
  178.         struct dev *dp;                 /* device */
  179.         char *fnm = NULL;               /* font name */
  180.         int err = 0;                    /* argument error count */
  181.         int fc, fx;                     /* file count and index */
  182.         struct font *fp;                /* font pointer */
  183.         FILE *fs;                       /* file stream */
  184.         int help = 0;                   /* -h status */
  185.         struct stat sbuf;               /* file stat() buffer */
  186.         char *sep;                      /* separator pointer */
  187. /*
  188.  * Save program name.
  189.  */
  190.         if ((Pname = strrchr(argv[0], '\\')) != NULL)
  191.                 Pname++;
  192.         else if ((Pname = strrchr(argv[0], '/')) != NULL)
  193.                 Pname++;
  194.         else
  195.                 Pname = argv[0];
  196. /*
  197.  * Process options.
  198.  */
  199.         while ((c = getopt(argc, argv, "c:d:f:h")) != EOF) {
  200.                 switch (c) {
  201.         /*
  202.          * -c config -- specify configuration file
  203.          */
  204.                 case 'c':
  205.                         if (cnm != NULL) {
  206.                                 (void) fprintf(stderr,
  207.                                         "%s: duplicate config name\n", Pname);
  208.                                 err = 1;
  209.                         } else
  210.                                 cnm = optarg;
  211.                         break;
  212.         /*
  213.          * -d device -- specify device
  214.          */
  215.                 case 'd':
  216.                         if (dnm != NULL) {
  217.                                 (void) fprintf(stderr,
  218.                                         "%s: duplicate device name\n", Pname);
  219.                                 err = 1;
  220.                         } else
  221.                                 dnm = optarg;
  222.                         break;
  223.         /*
  224.          * -f font -- specify font
  225.          */
  226.                 case 'f':
  227.                         if (fnm != NULL) {
  228.                                 (void) fprintf(stderr,
  229.                                         "%s: duplicate font name\n", Pname);
  230.                                 err = 1;
  231.                         } else
  232.                                 fnm = optarg;
  233.                         break;
  234.         /*
  235.          * -h -- request help
  236.          */
  237.                 case 'h':
  238.                         help++;
  239.                         break;
  240.         /*
  241.          * unknown option
  242.          */
  243.                 case '?':
  244.                         err = 1;
  245.                 }
  246.         }
  247. /*
  248.  * Handle file arguments.
  249.  */
  250.         if (optind >= argc)
  251.                 fc = 0;
  252.         else {
  253.                 fc = argc;
  254.                 for (fx = optind; fx < fc; fx++) {
  255.                         if (stat(argv[fx], &sbuf) != 0) {
  256.                                 (void) fprintf(stderr, "%s: can't find %s\n",
  257.                                         Pname, argv[fx]);
  258.                                 err++;
  259.                         }
  260.                 }
  261.         }
  262. /*
  263.  * Read configuration file.
  264.  */
  265.         if (Readcf(cnm) == 0)
  266.                 err++;
  267. /*
  268.  * Validate device name.
  269.  */
  270.         if (dnm == NULL)
  271.                 dnm = Defdev;
  272.         for (dp = Dp; dp; dp = dp->next) {
  273.                 if (strcmp(dnm, dp->nm) == 0)
  274.                         break;
  275.         }
  276.         if (dp) {
  277.                 if (fnm == NULL && dp->f)
  278.                         fnm = (dp->f)->nm;
  279.         } else {
  280.                 if (dnm == NULL)
  281.                         (void) fprintf(stderr, "%s: no device specified\n",
  282.                                 Pname);
  283.                 else
  284.                         (void) fprintf(stderr, "%s: unknown device: %s\n",
  285.                                 Pname, dnm);
  286.                 err++;
  287.                 dp = NULL;
  288.         }
  289. /*
  290.  * Validate font name.
  291.  */
  292.         if (fnm != NULL && dp) {
  293.                 for (fp = dp->f; fp; fp = fp->next) {
  294.                         if (strcmp(fnm, fp->nm) == 0)
  295.                                 break;
  296.                 }
  297.                 if (fp == NULL) {
  298.                         (void) fprintf(stderr,
  299.                                 "%s: font %s not defined for device %s\n",
  300.                                 Pname, fnm, dnm);
  301.                         err++;
  302.                 }
  303.         } else
  304.                 fp = NULL;
  305. /*
  306.  * Go no further if errors have been detected, or help has been requested.
  307.  */
  308.         if (err || help) {
  309.                 (void) fprintf(stderr,
  310.                         "%s usage: [-c config ] [-d device]", Pname);
  311.                 (void) fprintf(stderr,
  312.                         " [-f font] [file(s)]\n");
  313.                 (void) fprintf(stderr,
  314.                         "\t-c config    specify configuration file path\n");
  315.                 if (Conf != NULL) {
  316.                         (void) fprintf(stderr,
  317.                                 "\t             (currently using %s)\n", Conf);
  318.                 }
  319.                 (void) fprintf(stderr,
  320.                         "\t-d device    specify device name\n");
  321.                 if (Defdev != NULL) {
  322.                         (void) fprintf(stderr,
  323.                                 "\t             (default = %s)\n", Defdev);
  324.                 }
  325.                 (void) fprintf(stderr,
  326.                         "\t-f font      specify font name\n");
  327.                 (void) fprintf(stderr,
  328.                         "\tfile(s)      specify cawf -fe output files\n");
  329.                 (void) fprintf(stderr,
  330.                         "\t             (default = standard input)\n");
  331.                 (void) fprintf(stderr,
  332.                         "-d       -f (first font is default)\n");
  333.                 for (dp = Dp; dp; dp = dp->next) {
  334.                         (void) fprintf(stderr, "%-8.8s ", dp->nm);
  335.                         if ((fp = dp->f) == NULL)
  336.                                 (void) fprintf(stderr, "none\n");
  337.                         else {
  338.                                 sep = "";
  339.                                 while (fp) {
  340.                                         (void) fprintf(stderr,
  341.                                                 "%s%s", sep, fp->nm);
  342.                                         sep = "|";
  343.                                         fp = fp->next;
  344.                                 }
  345.                                 (void) putc('\n', stderr);
  346.                         }
  347.                 }
  348.                 if (err)
  349.                         exit(1);
  350.                 exit(0);
  351.         }
  352. /*
  353.  * Issue font selection, if any, and set up font escape string pointers.
  354.  */
  355.         if (fp && fp->fi)
  356.                 fputs(fp->fi, stdout);
  357.         Besc = dp->b;
  358.         Iesc = dp->i;
  359.         Resc = dp->r;
  360. /*
  361.  * Loop through the input files.
  362.  */
  363.         fx = optind;
  364.         do {
  365.  
  366.         /*
  367.          * If there are no files, use standard input (once).
  368.          */
  369.                 if (fc == 0)
  370.                         fs = stdin;
  371.                 else {
  372.         /*
  373.          * Open the named file.
  374.          */
  375. #ifdef  UNIX
  376.                         if ((fs = fopen(argv[fx], "r")) == NULL)
  377. #else
  378.                         if ((fs = fopen(argv[fx], "rt")) == NULL)
  379. #endif
  380.                         {
  381.                         (void) fprintf(stderr, "%s: can't open %s\n",
  382.                                 Pname, argv[fx]);
  383.                         exit(1);
  384.                         }
  385.                 }
  386.         /*
  387.          * Read and process the file.
  388.          */
  389.                 while ( ! feof(fs) && (c = getc(fs)) != EOF) {
  390.                         switch (c) {
  391.  
  392.                         case ESC:
  393.                                 Getec(fs);
  394.                                 if ( ! feof(fs) && (c = getc(fs)) != EOF)
  395.                                         putchar(c);
  396.                                 break;
  397.                         default:
  398.                                 Roman();
  399.                                 putchar(c);
  400.                                 break;
  401.                         }
  402.                 }
  403.                 if (fc != 0)
  404.                         (void) fclose(fs);
  405.         } while (++fx < fc);
  406.         exit(0);
  407. }
  408.  
  409.  
  410. /*
  411.  * Bold() - set bold font
  412.  */
  413.  
  414. static void
  415. Bold()
  416.  
  417. {
  418.         if (Font == BOLD)
  419.                 return;
  420.         if (Besc)
  421.                 fputs(Besc, stdout);
  422.         Font = BOLD;
  423. }
  424.  
  425.  
  426. /*
  427.  * Convfont(dp, s) - convert a font for a device
  428.  *
  429.  * entry:
  430.  *      dp = device structure pointer
  431.  *      s  = font definition string -- "name=initialization"
  432.  *
  433.  * exit:
  434.  *      return = 0 if errors detected
  435.  */
  436.  
  437. static int
  438. Convfont(dp, s)
  439.         struct dev *dp;                 /* device structure pointer */
  440.         char *s;                        /* font definition string */
  441. {
  442.         char *cp;                       /* temporary character pointer */
  443.         char *fn;                       /* font name */
  444.         struct font *fp;                /* font structure pointer */
  445.         struct font *tfp;               /* temporary font structure pointer */
  446. /*
  447.  * Get the font name allocate space for it and allocate space for
  448.  * a font structure.
  449.  */
  450.         if ((cp = strchr(s, '=')) == NULL) {
  451.                 (void) fprintf(stderr, "%s: bad %s font line format: %s\n",
  452.                         Pname, dp->nm, s);
  453.                 return(0);
  454.         }
  455.         if ((fn = malloc(cp - s + 1)) == NULL) {
  456.                 (void) fprintf(stderr, "%s: no space for %s font name %s\n",
  457.                         Pname, dp->nm, s);
  458.                 return(0);
  459.         }
  460.         (void) strncpy(fn, s, cp - s);
  461.         fn[cp - s] = '\0';
  462.         if ((fp = (struct font *)malloc(sizeof(struct font))) == NULL) {
  463.                 (void) fprintf(stderr, "%s: no space for %s font struct %s\n",
  464.                         Pname, dp->nm, fn);
  465.                 return(0);
  466.         }
  467. /*
  468.  * Fill in the font structure with the font name and the initialization
  469.  * string.
  470.  */
  471.         fp->nm = fn;
  472.         fp->next = NULL;
  473.         if (dp->f == NULL)
  474.                 dp->f = fp;
  475.         else {
  476.                 for (tfp = dp->f; tfp; tfp = tfp->next) {
  477.                         if (tfp->next == NULL) {
  478.                                 tfp->next = fp;
  479.                                 break;
  480.  
  481.                         }
  482.                 }
  483.         }
  484.         if ((fp->fi = Convstr(cp + 1)) == NULL)
  485.                 return(0);
  486.         return(1);
  487. }
  488.  
  489.  
  490. /*
  491.  * Convstr(s) - convert a string
  492.  *
  493.  * entry:
  494.  *      s = input string
  495.  *
  496.  * exit:
  497.  *      return = converted string address
  498.  *               NULL = error
  499.  */
  500.  
  501. static char *
  502. Convstr(s)
  503.         char *s;                        /* input string */
  504. {
  505.         int c;                          /* character assembly */
  506.         char *cp;                       /* temporary character pointer */
  507.         char *em;                       /* error message */
  508.         int i;                          /* temporary index */
  509.         int l;                          /* length */
  510.         char *r;                        /* result string */
  511. /*
  512.  * Make space for the result.
  513.  */
  514.         if ((r = malloc(strlen(s) + 1)) == NULL) {
  515.                 (void) fprintf(stderr, "%s: out of string space at %s\n",
  516.                         Pname, r);
  517.                 return(NULL);
  518.         }
  519. /*
  520.  * Copy the input string to the result, processing '\\' escapes.
  521.  */
  522.         for (cp = r; *s;) {
  523.                 switch (*s) {
  524.  
  525.                 case '\\':
  526.                         s++;
  527.                         if (*s >= '0' && *s <= '7') {
  528.                 /*
  529.                  * '\xxx' -- octal form
  530.                  */
  531.                                 for (c = i = 0; i < 3; i++, s++) {
  532.                                         if (*s < '0' || *s > '7') {
  533.                                                 em = "non-octal char";
  534. bad_string:
  535.                                                 (void) fprintf(stderr,
  536.                                                         "%s: %s : %s\n",
  537.                                                         Pname, em, r);
  538.                                                 return(NULL);
  539.                                         }
  540.                                         c = (c << 3) + *s - '0';
  541.                                 }
  542.                                 if (c > 0377) {
  543.                                         em = "octal char > 0377";
  544.                                         goto bad_string;
  545.                                 }
  546.                                 *cp++ = c;
  547.                         } else if (*s == 'x') {
  548.                 /*
  549.                  * '\xyy' -- hexadecimal form
  550.                  */
  551.                                 s++;
  552.                                 for (c = i = 0; i < 2; i++, s++) {
  553.                                         if ( ! isascii(*s) && ! isalpha(*s)
  554.                                         &&   ! isdigit(*s)) {
  555. non_hex_char:
  556.                                                 em = "non-hex char";
  557.                                                 goto bad_string;
  558.                                         }
  559.                                         c = c << 4;
  560.                                         if (*s >= '0' && *s <= '9')
  561.                                                 c += *s - '0';
  562.                                         else if ((*s >= 'a' && *s <= 'f')
  563.                                              ||  (*s >= 'A' && *s <= 'F'))
  564.                                                 c += *s + 10 -
  565.                                                      (isupper(*s) ? 'A' : 'a');
  566.                                         else
  567.                                                 goto non_hex_char;
  568.                                 }
  569.                                 *cp++ = c;
  570.                         } else if (*s == 'E' || *s == 'e') {
  571.                 /*
  572.                  * '\E' or '\e' -- ESCape
  573.                  */
  574.                                 *cp++ = ESC;
  575.                         } else if (*s == '\0') {
  576.                                 em = "no char after \\";
  577.                                 goto bad_string;
  578.                         } else
  579.                 /*
  580.                  * escaped character (for some reason)
  581.                  */
  582.                                 *cp++ = *s++;
  583.                         break;
  584.         /*
  585.          * Copy a "normal" character.
  586.          */
  587.                 default:
  588.                         *cp++ = *s++;
  589.                 }
  590.         }
  591.         *cp = '\0';
  592.         return(r);
  593. }
  594.  
  595.  
  596. /*
  597.  * Getec(fs) - get ESCape follower character
  598.  *
  599.  * entry:
  600.  *      fs = file stream
  601.  */
  602.  
  603. static void
  604. Getec(fs)
  605.         FILE *fs;                       /* file stream */
  606. {
  607.         register int c;
  608.  
  609.         if (feof(fs) || (c = getc(fs)) == EOF)
  610.                 return;
  611.         switch (c) {
  612.  
  613.         case ROMAN:
  614.                 Roman();
  615.                 break;
  616.         case ITALIC:
  617.                 Italic();
  618.                 break;
  619.         case BOLD:
  620.                 Bold();
  621.                 break;
  622.         default:
  623.                 (void) fprintf (stderr,
  624.                         "%s: unknown escape sequence ESC-0x%x\n",
  625.                         Pname, c);
  626.                 break;
  627.         }
  628. }
  629.  
  630.  
  631. /*
  632.  * Italic() - set italic font
  633.  */
  634.  
  635. static void
  636. Italic()
  637.  
  638. {
  639.         if (Font == ITALIC)
  640.                 return;
  641.         if (Iesc)
  642.                 fputs(Iesc, stdout);
  643.         Font = ITALIC;
  644. }
  645.  
  646.  
  647. /*
  648.  * Roman() - set Roman font
  649.  */
  650.  
  651. static void
  652. Roman()
  653.  
  654. {
  655.         if (Font == ROMAN)
  656.                 return;
  657.         if (Resc)
  658.                 fputs(Resc, stdout);
  659.         Font = ROMAN;
  660. }
  661.  
  662.  
  663. /*
  664.  * Readcf(p) - read configuration file
  665.  *
  666.  * entry:
  667.  *      p = configuration file path
  668.  *
  669.  * exit:
  670.  *      return = 0 if error detected
  671.  */
  672.  
  673. static int
  674. Readcf(p)
  675.         char *p;                        /* configuration file path */
  676. {
  677.         FILE *fs;                       /* file stream */
  678.         char *dn;                       /* device name */
  679.         struct dev *dp;                 /* device structure pointer */
  680.         int err = 0;                    /* errror count */
  681.         int l;                          /* length */
  682.         char line[MAXLINE];             /* line buffer */
  683.         char *s;                        /* temporary string pointer */
  684. /*
  685.  * If a path is supplied, use it.
  686.  */
  687.         if (p)
  688.                 Conf = p;
  689.         else {
  690.  
  691.         /*
  692.          * Use the CAWFLIB environment if it is defined.
  693.          */
  694.                 if ((Conf = getenv("CAWFLIB")) == NULL) 
  695.                         Conf = CAWFLIB;
  696.                 l = strlen(Conf) + 1 + strlen(p ? p : CONFIG) + 1;
  697.                 if ((s = malloc(l)) == NULL) {
  698.                         (void) fprintf(stderr, "%s: no space for %s name\n",
  699.                                 Pname,
  700.                                 p ? p : CONFIG);
  701.                         return(0);
  702.                 }
  703.                 (void) sprintf(s, "%s/%s", Conf, p ? p : CONFIG);
  704.                 Conf = s;
  705.         }
  706. /*
  707.  * Open the configuration file.
  708.  */
  709. #ifdef  UNIX
  710.         if ((fs = fopen(Conf, "r")) == NULL)
  711. #else
  712.         if ((fs = fopen(Conf, "rt")) == NULL)
  713. #endif
  714.         {
  715.                 (void) fprintf(stderr, "%s: can't open config file: %s\n",
  716.                         Pname, Conf);
  717.                 return(0);
  718.         }
  719.         *line = ' ';
  720. /*
  721.  * Look for a device definition line -- a line that begins with a name.
  722.  */
  723.         while ( ! feof(fs)) {
  724.                 if (isascii(*line) && (isspace(*line) || *line == '#')) {
  725.                         (void) fgets(line, MAXLINE, fs);
  726.                         continue;
  727.                 }
  728.                 if ((s = strrchr(line, '\n')) != NULL)
  729.                         *s = '\0';
  730.                 else
  731.                         line[MAXLINE-1] = '\0';
  732.         /*
  733.          * Allocate space for the name and the device structure.
  734.          */
  735.                 if ((dn = malloc(strlen(line) + 1)) == NULL) {
  736.                         (void) fprintf(stderr,
  737.                                 "%s: no string space for device %s\n",
  738.                                 Pname, line);
  739.                         return(0);
  740.                 }
  741.                 (void) strcpy(dn, line);
  742.                 if ((dp = (struct dev *)malloc(sizeof(struct dev))) == NULL) {
  743.                         (void) fprintf(stderr,
  744.                                 "%s: no space for structure for device %s\n",
  745.                                 Pname, dn);
  746.                         return(0);
  747.                 }
  748.                 dp->next = Dp;
  749.                 Dp = dp;
  750.                 Defdev = dp->nm = dn;
  751.                 dp->b = dp->i = dp->r = NULL;
  752.                 dp->f = NULL;
  753.         /*
  754.          * Read the parameter lines for the device.
  755.          */
  756.                 while (fgets(line, MAXLINE, fs) != NULL) {
  757.                         if ( ! isascii(*line) || *line != '\t')
  758.                                 break;
  759.                         if ( ! isascii(line[1]) || ! isalpha(line[1])
  760.                         ||   line[2] != '=')
  761.                                 break;
  762.                         if ((s = strrchr(line, '\n')) != NULL)
  763.                                 *s = '\0';
  764.                         else
  765.                                 line[MAXLINE-1] = '\0';
  766.                         switch (line[1]) {
  767.                 /*
  768.                  * \tb=<bolding_string>
  769.                  */
  770.                         case 'b':
  771.                                 if ((dp->b = Convstr(&line[3])) == NULL)
  772.                                         err++;
  773.                                 break;
  774.                 /*
  775.                  * \ti=<italicization_string>
  776.                  */
  777.                         case 'i':
  778.                                 if ((dp->i = Convstr(&line[3])) == NULL)
  779.                                         err++;
  780.                                 break;
  781.                 /*
  782.                  * \tr=<return_to_Roman_string>
  783.                  */
  784.                         case 'r':
  785.                                 if ((dp->r = Convstr(&line[3])) == NULL)
  786.                                         err++;
  787.                                 break;
  788.                 /*
  789.                  * \tf=<font_name>=<font_initialization_string>
  790.                  */
  791.                         case 'f':
  792.                                 if (Convfont(dp, &line[3]) == 0)
  793.                                         err++;
  794.                                 break;
  795.                 /*
  796.                  * ????
  797.                  */
  798.                         default:
  799.                                 (void) fprintf(stderr,
  800.                                         "%s: unknown device %s line %s\n",
  801.                                         Pname, dp->nm, line);
  802.                                 err++;
  803.                         }
  804.                 }
  805.         }
  806.         (void) fclose(fs);
  807.         if (err)
  808.                 return(0);
  809.         return(1);
  810. }
  811.